<template>
    <el-dialog v-model="isOpen" title="Z-Score异常检测结果" :border="true" align-center>
        <el-descriptions column="1" border>
            <el-descriptions-item label="均值">{{ result.mean.toFixed(4) }}</el-descriptions-item>
            <el-descriptions-item label="标准差">{{ result.stdDev.toFixed(4) }}</el-descriptions-item>
            <el-descriptions-item label="异常点索引">
                <span v-if="result.anomalyIndices.length === 0">无异常点</span>
                <span v-else>
                    <span v-for="(index, i) in result.anomalyIndices" :key="i">
                        {{ index }}{{ i < result.anomalyIndices.length - 1 ? ", " : "" }}
                    </span>
                </span>
            </el-descriptions-item>
        </el-descriptions>

        <el-divider />

        <div ref="chartContainer" style="width: 100%;height: 400px" />

        <template #footer>
            <div class="dialog-footer">
                <el-button type="primary" @click="isOpen = false">关闭</el-button>
            </div>
        </template>
    </el-dialog>
</template>

<script setup>
import { nextTick, ref, watch } from "vue"
import * as echarts             from "echarts"

let isOpen = defineModel()
let props  = defineProps([ "originalData", "result" ])

let chartContainer = ref(null)
let chartInstance  = ref(null)

watch(isOpen, (val) => {
    if(val){
        initChart()
    }
})

function initChart(){
    nextTick(() => {
        if(!chartContainer.value){
            return
        }
        if(!props.result){
            return
        }
        if(!props.originalData || !props.originalData.data){
            return
        }

        const data      = props.originalData.data
        const threshold = props.originalData.threshold || 2

        if(!chartInstance.value){
            chartInstance.value = echarts.init(chartContainer.value)
        }

        // 准备数据，标记异常点
        const dataPoints = data.map((value, index) => {
            const isAnomaly = props.result.anomalyIndices.includes(index)
            return {
                value     : [ index, value ],
                itemStyle : {
                    color: isAnomaly ? "#e74c3c" : "#3498db",
                },
                symbolSize: isAnomaly ? 15 : 10,
                zscore    : props.result.zscores[index],
            }
        })

        // Z分数数据
        const zscoreData = props.result.zscores.map((zscore, index) => [ index, zscore ])

        let indexs = props.originalData.indexs

        const option = {
            tooltip   : {
                trigger  : "item",
                formatter: (params) => {
                    const index = params.dataIndex
                    return `索引: ${ index }<br/>
                            数值: ${ data[index] }<br/>
                            Z分数: ${ props.result.zscores[index].toFixed(4) }<br/>
                            类型: ${ props.result.anomalyIndices.includes(index) ? "异常点" : "正常点" }`
                },
            },
            grid      : [
                {
                    left        : "5%",
                    right       : "10%",
                    bottom      : "55%",
                    top         : "10%",
                    containLabel: true,
                },
                {
                    left        : "5%",
                    right       : "10%",
                    bottom      : "10%",
                    top         : "55%",
                    containLabel: true,
                },
            ],
            xAxis     : [
                {
                    type     : "category",
                    name     : "数据索引",
                    gridIndex: 0,
                    data     : indexs,
                },
                {
                    type     : "category",
                    name     : "数据索引",
                    gridIndex: 1,
                    data     : indexs,
                },
            ],
            yAxis     : [
                {
                    type     : "value",
                    name     : "原始值",
                    gridIndex: 0,
                },
                {
                    type     : "value",
                    name     : "Z分数",
                    gridIndex: 1,
                    // 添加阈值参考线
                    splitLine: {
                        lineStyle: {
                            type: "dashed",
                        },
                    },
                },
            ],
            series    : [
                // 原始数据
                {
                    type      : "scatter",
                    name      : "原始数据",
                    data      : dataPoints,
                    xAxisIndex: 0,
                    yAxisIndex: 0,
                    z         : 2,
                },
                // 均值线
                {
                    type      : "line",
                    name      : "均值",
                    data      : data.map((_, index) => [ index, props.result.mean ]),
                    xAxisIndex: 0,
                    yAxisIndex: 0,
                    lineStyle : {
                        color: "#2ecc71",
                        type : "dashed",
                    },
                    symbol    : "none",
                    z         : 1,
                },
                // Z分数
                {
                    type      : "scatter",
                    name      : "Z分数",
                    data      : zscoreData,
                    xAxisIndex: 1,
                    yAxisIndex: 1,
                    itemStyle : {
                        color: (params) => {
                            const index = params.dataIndex
                            return props.result.anomalyIndices.includes(index) ? "#e74c3c" : "#3498db"
                        },
                    },
                    symbolSize: 10,
                    z         : 2,
                },
                // 正阈值线
                {
                    type      : "line",
                    name      : "阈值",
                    data      : data.map((_, index) => [ index, threshold ]),
                    xAxisIndex: 1,
                    yAxisIndex: 1,
                    lineStyle : {
                        color: "#f39c12",
                        type : "dashed",
                    },
                    symbol    : "none",
                    z         : 1,
                },
                // 负阈值线
                {
                    type      : "line",
                    data      : data.map((_, index) => [ index, -threshold ]),
                    xAxisIndex: 1,
                    yAxisIndex: 1,
                    lineStyle : {
                        color: "#f39c12",
                        type : "dashed",
                    },
                    symbol    : "none",
                    z         : 1,
                },
            ],
            annotation: {
                label: {
                    fontSize: 12,
                    color   : "#333",
                },
                data : [
                    {
                        type      : "text",
                        position  : [ "50%", "48%" ],
                        value     : `异常阈值: ±${ threshold }`,
                        xAxisIndex: 0,
                        yAxisIndex: 0,
                    },
                ],
            },
        }

        chartInstance.value.setOption(option)

        window.onresize = function(){
            chartInstance.value.resize()
        }
    })
}
</script>

<style lang="scss" scoped>
</style>
